#include <Windows.h>
#include <stdio.h>
#include <stdint.h>
#include <malloc.h>

uint8_t Exploit[] =
	"AAAAAAAAAAAAAAAA"  // 16 bytes for buffer length
	"\xde\xc0\xad\xde"  // New EIP 0xdeadc0de
	"\x1c\xff\x19\x00"; // 0x0019FF1c

uint32_t gdwGlobalVar = 0;

void OverflowGeneric(uint8_t* pInputBuf, uint32_t dwInputBufSize) {
	char Buf[16];
	uint32_t dwVar1 = 1;
	uint32_t* pdwVar2 = &gdwGlobalVar;

	memcpy(Buf, pInputBuf, dwInputBufSize);
	*pdwVar2 = dwVar1;
}

void OverflowOOBW(uint8_t* pInputBuf, uint32_t dwInputBufSize) {
	uint8_t Buf[16];
	uint32_t dwVar1 = 1;
	uint32_t* pdwVar2 = &gdwGlobalVar;

	for (uint32_t dwX = 0; dwX < dwInputBufSize; dwX++) {
		Buf[dwX] = pInputBuf[dwX];
	}

	*pdwVar2 = dwVar1;
}

void OverflowGeneric_4(uint8_t* pInputBuf, uint32_t dwInputBufSize) {
	uint32_t Buf[16];
	uint32_t dwVar1 = 1;
	uint32_t* pdwVar2 = &gdwGlobalVar;

	memcpy(Buf, pInputBuf, dwInputBufSize);
	*pdwVar2 = dwVar1;
}

struct MyStruct {
	char Buf[16];
	uint32_t dwVar1;
	uint32_t* pdwVar2;
};

void OverflowStructArray(uint8_t* pInputBuf, uint32_t dwInputBufSize) {
	struct MyStruct TestStruct = { 0 };
	TestStruct.dwVar1 = 0x12345678;
	TestStruct.pdwVar2 = &gdwGlobalVar;
	memcpy(TestStruct.Buf, pInputBuf, dwInputBufSize);
	*TestStruct.pdwVar2 = TestStruct.dwVar1;
}

class MyClass {
public:
	char Buf[16];
	uint32_t dwVar1;
	uint32_t* pdwVar2;
	MyClass();
};

MyClass::MyClass() {
	printf("... MyClass constructor called\r\n");
	this->dwVar1 = 0x12345678;
}

void OverflowClass(uint8_t* pInputBuf, uint32_t dwInputBufSize) {
	MyClass TestClass;
	TestClass.pdwVar2 = &gdwGlobalVar;
	memcpy(TestClass.Buf, pInputBuf, dwInputBufSize);
	*TestClass.pdwVar2 = TestClass.dwVar1;
}

void OverflowAlloca(uint8_t * pInputBuf, uint32_t dwInputBufSize) {
	uint32_t dwValue = 1;
	uint32_t* pgdwGlobalVar = &gdwGlobalVar;
	char* Buf = (char*)_alloca(16);
	memcpy(Buf, pInputBuf, dwInputBufSize);
	*pgdwGlobalVar = dwValue;
}

int32_t wmain(int32_t nArgc, const wchar_t* pArgv[]) {
	printf("... passing %d bytes of data to vulnerable function\r\n", sizeof(Exploit) - 1);
	//OverflowGeneric(Exploit, sizeof(Exploit) - 1);
	OverflowOOBW(Exploit, sizeof(Exploit) - 1);
	//OverflowClass(Exploit, sizeof(Exploit) - 1);
	//OverflowAlloca(Exploit, sizeof(Exploit) - 1);
	return 0;
}